<template>
  <div class="layout-root">
    <aside class="sidebar" :class="{ collapsed: collapsed }">
      <div class="sidebar-logo">
        <span class="logo-title">X Boot</span>
      </div>
      <el-menu
        :default-active="$route.path"
        class="sidebar-menu"
        background-color="var(--el-menu-bg-color)"
        text-color="var(--el-menu-text-color)"
        active-text-color="var(--el-menu-active-color)"
        router
        :collapse="collapsed"
      >
        <el-menu-item index="/dashboard">
          <el-icon><DataAnalysis /></el-icon>
          <span v-if="!collapsed">仪表盘</span>
        </el-menu-item>
        <el-sub-menu index="1">
          <template #title>
            <el-icon><Setting /></el-icon>
            <span v-if="!collapsed">系统管理</span>
          </template>
          <el-menu-item index="/user">
            <el-icon><User /></el-icon>
            <span v-if="!collapsed">用户管理</span>
          </el-menu-item>
          <el-menu-item index="/role">
            <el-icon><UserFilledIcon /></el-icon>
            <span v-if="!collapsed">角色管理</span>
          </el-menu-item>
          <el-menu-item index="/permission">
            <el-icon><Lock /></el-icon>
            <span v-if="!collapsed">权限管理</span>
          </el-menu-item>
          <el-menu-item index="/log">
            <el-icon><Document /></el-icon>
            <span v-if="!collapsed">日志管理</span>
          </el-menu-item>
        </el-sub-menu>
        <el-menu-item index="/terminal">
          <el-icon><Connection /></el-icon>
          <span v-if="!collapsed">权限终端</span>
        </el-menu-item>
        <el-menu-item index="/test">
          <el-icon><Lock /></el-icon>
          <span v-if="!collapsed">权限测试页</span>
        </el-menu-item>
      </el-menu>
    </aside>
    <div class="layout-main" :class="{ collapsed: collapsed }">
      <header class="layout-header breadcrumb-header">
        <div class="header-left">
          <el-icon style="font-size:22px;cursor:pointer;margin-right:8px;" @click="toggleAside">
            <Menu v-if="!collapsed" />
            <Fold v-else />
          </el-icon>
          <el-breadcrumb separator="/">
            <el-breadcrumb-item v-for="(bc, idx) in breadcrumbs" :key="bc.path">
              <span v-if="idx === breadcrumbs.length - 1">{{ bc.title }}</span>
              <router-link v-else :to="bc.path">{{ bc.title }}</router-link>
            </el-breadcrumb-item>
          </el-breadcrumb>
        </div>
        <div class="header-right">
          <el-icon style="margin: 0 16px 0 0;cursor:pointer;" @click="toggleFullScreen"><FullScreen /></el-icon>
          <ThemeSwitcher style="margin-right: 16px;" />
          <span style="font-size: 14px; color:#222; margin-right: 16px;">{{ username || '用户' }}</span>
          <el-dropdown>
            <span class="avatar-btn" style="display:inline-block;cursor:pointer;">
              <UserAvatar ref="userAvatarRef" :avatarKey="avatarKey" />
            </span>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item @click="showProfileDialog = true">更换头像</el-dropdown-item>
                <el-dropdown-item @click="showProfileInfoDialog = true">个人信息</el-dropdown-item>
                <el-dropdown-item @click="onChangePassword">修改密码</el-dropdown-item>
                <el-dropdown-item divided @click="onLogout">退出登录</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </div>
      </header>
      
      <!-- 路由标签栏 -->
      <div class="route-tabs">
        <div class="tabs-container">
          <div 
            v-for="tab in routeTabs" 
            :key="tab.path"
            :class="['tab-item', { active: tab.path === $route.path }]"
            @click="switchTab(tab.path)"
          >
            <span class="tab-title">{{ tab.title }}</span>
            <el-icon 
              v-if="routeTabs.length > 1 && tab.path !== '/dashboard'"
              class="tab-close" 
              @click.stop="closeTab(tab.path)"
            >
              <Close />
            </el-icon>
          </div>
        </div>
      </div>
      
      <main class="layout-content" ref="mainContent">
        <router-view v-slot="{ Component }">
          <transition name="page-transition" mode="out-in" @after-enter="scrollToTop">
            <component :is="Component" :key="$route.fullPath" />
          </transition>
        </router-view>

        <!-- 个人信息弹窗 -->
        <el-dialog v-model="showProfileDialog" title="更换头像" width="400px">
          <div style="text-align:center;">
            <div class="avatar-preview-container">
              <UserAvatar v-if="!previewAvatarUrl" :avatarKey="avatarKey" class="avatar-preview" />
              <img v-else :src="previewAvatarUrl" class="avatar-preview" />
            </div>
            <el-upload
              ref="uploadRef"
              class="avatar-uploader"
              :show-file-list="false"
              :on-change="handleAvatarChange"
              :before-upload="beforeAvatarUpload"
              :auto-upload="false"
              accept="image/*"
            >
              <el-button type="primary">选择头像文件</el-button>
            </el-upload>
            <div style="color:#888; font-size:12px; margin-top:8px;">支持 JPG、PNG 格式，文件大小不超过 2MB</div>
          </div>
          <template #footer>
            <el-button @click="showProfileDialog=false">取消</el-button>
            <el-button type="primary" @click="handleProfileOk">确定</el-button>
          </template>
        </el-dialog>

        <!-- 修改密码弹窗 -->
        <ChangePasswordDialog v-model="showChangePwd" />

        <!-- 个人信息弹窗 -->
        <el-dialog v-model="showProfileInfoDialog" title="个人信息" width="400px">
          <el-form :model="profileForm" label-width="80px">
            <el-form-item label="手机号">
              <el-input v-model="profileForm.phone" placeholder="待填写" />
            </el-form-item>
            <el-form-item label="邮箱">
              <el-input v-model="profileForm.email" placeholder="待填写" />
            </el-form-item>
          </el-form>
          <template #footer>
            <el-button @click="showProfileInfoDialog = false">取消</el-button>
            <el-button type="primary" @click="onSaveProfile">保存</el-button>
          </template>
        </el-dialog>
      </main>
    </div>
  </div>
</template>

<script setup>
import { ref, nextTick, watch, computed, reactive } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { ElMessageBox, ElMessage, ElDialog, ElInput } from 'element-plus'
import ThemeSwitcher from '../components/ThemeSwitcher.vue'
import UserAvatar from '../components/UserAvatar.vue'
import ChangePasswordDialog from '../components/ChangePasswordDialog.vue'
import { Menu, FullScreen, Bell, UserFilled, DataAnalysis, Setting, User, UserFilled as UserFilledIcon, Menu as MenuIcon, Document, Connection, Lock, Fold, Close } from '@element-plus/icons-vue'
import { BASE_URL } from '@/api/baseurl.js'
import axios from 'axios'
import { getUserContactInfo } from '@/api/user.js'

const collapsed = ref(false)
function toggleAside() {
  collapsed.value = !collapsed.value
}

const username = ref(localStorage.getItem('username') || '')

const mainContent = ref(null)
function scrollToTop() {
  nextTick(() => {
    if (mainContent.value) {
      mainContent.value.scrollTop = 0
    }
  })
}

const router = useRouter()
const route = useRoute()

// 路由标签管理
const routeTabs = ref([
  { path: '/dashboard', title: '仪表盘' }
])

// 添加路由标签
const addRouteTab = (path, title) => {
  const existingTab = routeTabs.value.find(tab => tab.path === path)
  if (!existingTab) {
    routeTabs.value.push({ path, title })
  }
}

// 切换路由标签
const switchTab = (path) => {
  router.push(path)
}

// 关闭路由标签
const closeTab = (path) => {
  // 防止删除仪表盘
  if (path === '/dashboard') {
    return
  }
  
  const index = routeTabs.value.findIndex(tab => tab.path === path)
  if (index > -1) {
    routeTabs.value.splice(index, 1)
    
    // 如果关闭的是当前标签，跳转到上一个标签
    if (path === route.path) {
      const nextTab = routeTabs.value[index] || routeTabs.value[index - 1]
      if (nextTab) {
        router.push(nextTab.path)
      }
    }
  }
}

// 监听路由变化，自动添加标签
watch(() => route.path, (newPath) => {
  if (newPath && route.meta?.title) {
    addRouteTab(newPath, route.meta.title)
  }
}, { immediate: true })

// 确保仪表盘始终在第一个位置
watch(() => routeTabs.value, (newTabs) => {
  const dashboardTab = newTabs.find(tab => tab.path === '/dashboard')
  if (!dashboardTab) {
    routeTabs.value.unshift({ path: '/dashboard', title: '仪表盘' })
  } else if (newTabs.indexOf(dashboardTab) !== 0) {
    // 如果仪表盘不在第一个位置，移动到第一个位置
    const dashboardIndex = newTabs.indexOf(dashboardTab)
    routeTabs.value.splice(dashboardIndex, 1)
    routeTabs.value.unshift(dashboardTab)
  }
}, { deep: true })

// 动态面包屑
const breadcrumbs = computed(() => {
  return route.matched
    .filter(r => r.meta && r.meta.title)
    .map(r => ({
      path: r.path,
      title: r.meta.title
    }))
})

function onLogout() {
  ElMessageBox.confirm('确定要退出登录吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    // 清除登录状态等
    localStorage.removeItem('isLogin')
    localStorage.removeItem('token')
    localStorage.removeItem('username')
    router.replace('/login')
  })
}


const showProfileDialog = ref(false)
const showChangePwd = ref(false)
const showProfileInfoDialog = ref(false)
const pwdForm = ref({ oldPwd: '', newPwd: '', confirmPwd: '' })
const pwdFormRef = ref()

const uploadRef = ref()
const avatarKey = ref(Date.now())
const userAvatarRef = ref()
let uploadPending = false
const previewAvatarUrl = ref('')
const oldAvatarFileName = ref('')
let newAvatarFile = null

const profileForm = reactive({
  phone: '',
  email: ''
})
const profileEditMode = ref(true)

// 获取用户联系方式
async function fetchContactInfo() {
  try {
    const userId = localStorage.getItem('userId')
    const token = localStorage.getItem('token')
    const res = await getUserContactInfo(userId, token)
    if (res && res.Data) {
      profileForm.phone = res.Data.Phone ?? ''
      profileForm.email = res.Data.Email ?? ''
    }
  } catch (e) {
    ElMessage.error('获取个人信息失败')
  }
}

watch(showProfileInfoDialog, (val) => {
  if (val) {
    fetchContactInfo()
  }
})

function onEditProfile() {
  profileEditMode.value = true
}

async function onSaveProfile() {
  try {
    const userId = localStorage.getItem('userId')
    const token = localStorage.getItem('token')
    await axios.post(BASE_URL + '/api/user/contact-info', {
      userId,
      phone: profileForm.phone,
      email: profileForm.email
    }, {
      headers: { Authorization: `Bearer ${token}` }
    })
    profileEditMode.value = false
    ElMessage.success('保存成功')
    fetchContactInfo()
    showProfileInfoDialog.value = false
  } catch (e) {
    ElMessage.error('保存失败')
  }
}

// 打开弹窗时获取当前头像
const fetchCurrentAvatar = async () => {
  try {
    const userId = localStorage.getItem('userId')
    if (!userId) {
      oldAvatarFileName.value = ''
      previewAvatarUrl.value = ''
      return
    }
    const token = localStorage.getItem('token')
    const res = await fetch(`${BASE_URL}/api/Image/user/${userId}`, {
      headers: {
        Authorization: `Bearer ${token}`
      }
    })
    const result = await res.json()
    if (result && result.Data && Array.isArray(result.Data) && result.Data.length > 0) {
      oldAvatarFileName.value = result.Data[0].FileName
      previewAvatarUrl.value = '' // 默认显示UserAvatar组件
    } else {
      oldAvatarFileName.value = ''
      previewAvatarUrl.value = ''
    }
  } catch (error) {
    console.error('获取用户头像失败:', error)
    oldAvatarFileName.value = ''
    previewAvatarUrl.value = ''
  }
}
watch(showProfileDialog, (val) => {
  if (val) fetchCurrentAvatar()
  else {
    previewAvatarUrl.value = ''
    newAvatarFile = null
  }
})

const handleAvatarChange = (file) => {
  try {
    if (file && file.raw) {
      previewAvatarUrl.value = URL.createObjectURL(file.raw)
      newAvatarFile = file.raw
    } else {
      console.error('文件对象无效:', file)
      ElMessage.error('文件选择失败')
    }
  } catch (error) {
    console.error('处理头像文件时出错:', error)
    ElMessage.error('处理头像文件时出错')
  }
}

async function handleProfileOk() {
  try {
    // 检查是否有选择新头像文件
    if (newAvatarFile) {
      uploadPending = true
      // 创建FormData
      const formData = new FormData()
      formData.append('file', newAvatarFile)
      formData.append('userId', localStorage.getItem('userId'))
      formData.append('tags', 'avatar')
      formData.append('description', '用户头像')
      try {
        const token = localStorage.getItem('token')
        const response = await fetch(`${BASE_URL}/api/Image/upload`, {
          method: 'POST',
          body: formData,
          headers: {
            Authorization: `Bearer ${token}`
          }
        })
        if (response.status === 401) {
          ElMessage.error('未登录或登录已过期，请重新登录')
          uploadPending = false
          return
        }
        const result = await response.json()
        
        if (result && (result.code === 200 || result.Code === 200)) {
          ElMessage.success('头像上传成功！')
          avatarKey.value = Date.now() // 强制刷新UserAvatar组件
          // 主动刷新UserAvatar组件
          if (userAvatarRef.value && userAvatarRef.value.refresh) {
            await userAvatarRef.value.refresh()
          }
          // 触发localStorage事件，通知其他组件头像已更新
          localStorage.setItem('avatarUpdated', Date.now().toString())
          previewAvatarUrl.value = ''
          showProfileDialog.value = false
          uploadPending = false
          newAvatarFile = null
          // 跳转到用户管理并强制刷新
          if (route.path === '/user') {
            router.push('/user?refresh=' + Date.now())
          }
        } else {
          ElMessage.error(`头像上传失败: ${result?.message || '未知错误'}`)
          uploadPending = false
        }
      } catch (error) {
        console.error('上传请求失败:', error)
        ElMessage.error('上传请求失败')
      }
    } else {
      // 没有选择新头像
      showProfileDialog.value = false
      ElMessage.info('请选择头像文件')
    }
  } catch (error) {
    console.error('上传请求失败:', error)
    ElMessage.error('上传请求失败')
  }
}

const handleUploadSuccess = async (response) => {
  if (response && (response.code === 200 || response.Code === 200)) {
    // 后端已经在上传时自动删除了旧头像，这里不需要手动删除
    // 注释掉手动删除的代码，避免 404
    // if (oldAvatarFileName.value) {
    //   try {
    //     const deleteResponse = await fetch(`${BASE_URL}/api/Image/${oldAvatarFileName.value}`, { 
    //       method: 'DELETE',
    //       headers: {
    //         Authorization: `Bearer ${localStorage.getItem('token')}`
    //       }
    //     })
    //     
    //     if (deleteResponse.ok) {
    //       console.log('删除旧头像成功:', oldAvatarFileName.value)
    //     } else {
    //       console.warn(`删除旧头像失败: ${deleteResponse.status} ${deleteResponse.statusText}`)
    //     }
    //   } catch (deleteError) {
    //     console.error('删除旧头像失败:', deleteError)
    //   }
    // }
    ElMessage.success('头像上传成功！')
    avatarKey.value = Date.now()
    previewAvatarUrl.value = ''
    showProfileDialog.value = false
    uploadPending = false
  } else {
    ElMessage.error('头像上传失败')
    uploadPending = false
  }
}

const beforeAvatarUpload = (file) => {
  const isImage = file.type.startsWith('image/')
  const isLt2M = file.size / 1024 / 1024 < 2
  if (!isImage) {
    ElMessage.error('只能上传图片文件!')
  }
  if (!isLt2M) {
    ElMessage.error('图片大小不能超过 2MB!')
  }
  return isImage && isLt2M
}

const uploadData = () => {
  return {
    userId: localStorage.getItem('userId'),
    tags: 'avatar',
    description: '用户头像'
  }
}

function onChangePassword() {
  showChangePwd.value = true
}

// 全屏切换逻辑
function toggleFullScreen() {
  const doc = document.documentElement;
  if (!document.fullscreenElement) {
    if (doc.requestFullscreen) {
      doc.requestFullscreen();
    } else if (doc.webkitRequestFullScreen) {
      doc.webkitRequestFullScreen();
    } else if (doc.mozRequestFullScreen) {
      doc.mozRequestFullScreen();
    } else if (doc.msRequestFullscreen) {
      doc.msRequestFullscreen();
    }
  } else {
    if (document.exitFullscreen) {
      document.exitFullscreen();
    } else if (document.webkitCancelFullScreen) {
      document.webkitCancelFullScreen();
    } else if (document.mozCancelFullScreen) {
      document.mozCancelFullScreen();
    } else if (document.msExitFullscreen) {
      document.msExitFullscreen();
    }
  }
}
</script>

<style scoped>
.layout-root {
  display: flex;
  height: 100vh;
  min-height: 100vh;
  overflow: hidden;
}
.sidebar {
  width: 220px;
  height: 100vh;
  min-height: 100vh;
  background: linear-gradient(135deg, #6ea8fe 0%, #a7bfff 100%);
  color: var(--el-menu-text-color);
  display: flex;
  flex-direction: column;
  box-shadow: none;
  margin: 0;
  padding: 0;
  border: none;
  transition: width 0.25s cubic-bezier(0.4,0,0.2,1);
}
.sidebar.collapsed {
  width: 64px;
  transition: width 0.25s cubic-bezier(0.4,0,0.2,1);
}
.sidebar-logo {
  display: flex;
  align-items: center;
  height: 56px;
  padding-left: 18px;
  background: var(--sidebar-logo-bg, linear-gradient(180deg, #e9eef6 0%, #c9d6e6 100%));
  border-bottom: none;
}
:root[data-theme='blue'] .sidebar-logo {
  background: linear-gradient(180deg, color-mix(in srgb, var(--el-color-primary) 90%, #1a237e 10%) 0%, color-mix(in srgb, var(--el-color-primary) 60%, #1a237e 40%) 100%);
}
:root[data-theme='glass'] .sidebar-logo {
  background: linear-gradient(180deg, #4f7cf7 0%, #6ea8fe 100%) !important;
  border-bottom: none;
}
.logo-img {
  width: 32px;
  height: 32px;
  margin-right: 10px;
}
.logo-title {
  font-size: 18px;
  font-weight: bold;
  letter-spacing: 1px;
  transition: font-size 0.2s, opacity 0.2s;
}
.sidebar.collapsed .logo-title {
  font-size: 12px;
  opacity: 1;
}
.sidebar-menu {
  flex: 1;
  border: none;
  background: var(--el-menu-bg-color);
}
.sidebar-menu .el-menu-item,
.sidebar-menu .el-sub-menu__title {
  display: flex;
  align-items: center;
  height: 44px;
  padding-left: 24px;
  font-size: 15px;
}
.sidebar-menu .el-icon {
  font-size: 20px !important;
  margin-right: 18px;
  min-width: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.layout-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  height: 100vh;
  width: calc(100vw - 220px);
  overflow: hidden;
  background: none;
  transition: width 0.25s cubic-bezier(0.4,0,0.2,1);
}
.layout-main.collapsed {
  width: calc(100vw - 64px);
  transition: width 0.25s cubic-bezier(0.4,0,0.2,1);
}
.layout-header {
  height: 60px;
  background: #fff;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 24px;
  border-bottom: 1px solid #f0f0f0;
  flex-shrink: 0;
  position: sticky;
  top: 0;
  z-index: 10;
}
.layout-title {
  font-size: 20px;
  font-weight: bold;
}
.layout-content {
  flex: 1 1 0;
  overflow: hidden;
  padding: 24px;
  padding-top: 16px;
  position: relative;
  background: #f5f6fa;
  min-height: 0;
  will-change: scroll-position;
}

/* 页面切换动画 */
.page-transition-enter-active,
.page-transition-leave-active {
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

.page-transition-enter-from {
  opacity: 0;
  transform: translateX(20px);
}

.page-transition-leave-to {
  opacity: 0;
  transform: translateX(-20px);
}

.page-transition-enter-to,
.page-transition-leave-from {
  opacity: 1;
  transform: translateX(0);
}

/* 防止 body 出现滚动条 */
:global(body) {
  overflow: hidden;
}

.avatar-btn {
  vertical-align: middle;
}

.breadcrumb-header {
  background: #fff;
  color: #222;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 48px;
  padding: 8px 24px;
  box-shadow: 0 2px 8px rgba(64,158,255,0.04);
  border-bottom: 1px solid #f0f0f0;
}
.header-left {
  display: flex;
  align-items: center;
}
.header-right {
  display: flex;
  align-items: center;
}

/* 路由标签栏样式 */
.route-tabs {
  background: var(--el-bg-color, #fafbfc);
  border-bottom: 1px solid var(--el-border-color, #e1e5e9);
  padding: 0 20px;
  height: 52px;
  display: flex;
  align-items: center;
  flex-shrink: 0;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  position: relative;
  z-index: 10;
}

.tabs-container {
  display: flex;
  align-items: center;
  gap: 4px;
  height: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 8px 0;
}

.tab-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  background: var(--el-bg-color, #ffffff);
  border: 1px solid var(--el-border-color, #e1e5e9);
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  white-space: nowrap;
  min-width: 90px;
  max-width: 200px;
  position: relative;
  font-size: 13px;
  color: var(--el-text-color-primary, #606266);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);
}

.tab-item:hover {
  background: var(--el-fill-color-light, #f8f9fa);
  border-color: var(--el-border-color, #d1d5db);
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.tab-item.active {
  background: linear-gradient(135deg, var(--el-color-primary, #409eff) 0%, var(--el-color-primary-light-3, #337ecc) 100%);
  border-color: var(--el-color-primary, #409eff);
  color: white;
  box-shadow: 0 2px 8px rgba(var(--el-color-primary-rgb, 64, 158, 255), 0.3);
  transform: translateY(-1px);
}

.tab-title {
  font-size: 13px;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
  line-height: 1.3;
}

.tab-close {
  font-size: 12px;
  opacity: 0.6;
  transition: all 0.2s ease;
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  color: var(--el-text-color-primary, #606266);
}

.tab-close:hover {
  opacity: 1;
  background: var(--el-fill-color-dark, rgba(0, 0, 0, 0.1));
  transform: scale(1.1);
}

.tab-item.active .tab-close {
  color: white;
  opacity: 0.8;
}

.tab-item.active .tab-close:hover {
  background: rgba(255, 255, 255, 0.2);
  opacity: 1;
}

/* 滚动条样式 */
.tabs-container::-webkit-scrollbar {
  height: 3px;
}

.tabs-container::-webkit-scrollbar-track {
  background: transparent;
}

.tabs-container::-webkit-scrollbar-thumb {
  background: var(--el-border-color, #d1d5db);
  border-radius: 2px;
}

.tabs-container::-webkit-scrollbar-thumb:hover {
  background: var(--el-text-color-secondary, #9ca3af);
}

.sidebar-menu.el-menu--collapse .el-menu-item,
.sidebar-menu.el-menu--collapse .el-sub-menu__title {
  padding-left: 18px !important;
}
.sidebar-menu.el-menu--collapse .el-icon {
  margin-right: 0 !important;
  min-width: 20px;
}
.sidebar-menu .el-menu-item.is-active, 
.sidebar-menu .el-sub-menu.is-opened > .el-sub-menu__title {
  background: var(--el-menu-active-color, #409EFF) !important;
  color: #fff !important;
  box-shadow: 0 2px 8px rgba(64,158,255,0.10);
}

/** 统一弹窗内容垂直居中和footer按钮右对齐样式 **/
:deep(.el-dialog__body) {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 120px;
}
:deep(.el-dialog__footer) {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

/** 让所有el-dialog弹窗窗口本身在屏幕垂直居中显示，并且所有弹窗位置一致 **/
:deep(.el-dialog) {
  top: 50% !important;
  transform: translateY(-50%) !important;
  margin: 0 auto !important;
}

.avatar-preview-container {
  display: flex;
  justify-content: center;
  align-items: center;
  margin-bottom: 16px;
  min-height: 180px;
}

.avatar-preview {
  width: 180px !important;
  height: 180px !important;
  border-radius: 8px !important;
  box-shadow: 0 2px 8px rgba(0,0,0,0.08) !important;
  object-fit: cover;
}

/* 确保 el-avatar 组件也使用相同的大小 */
.avatar-preview-container :deep(.el-avatar) {
  width: 180px !important;
  height: 180px !important;
  border-radius: 8px !important;
  box-shadow: 0 2px 8px rgba(0,0,0,0.08) !important;
}

.avatar-preview-container :deep(.el-avatar img) {
  border-radius: 8px !important;
}
</style>

